﻿#include "stk_dump.h"
#include <stdio.h>
#include <string.h>
#include <malloc.h>

#include <stddef.h>

//#pragma comment(lib, "imagehlp.lib")
//#pragma warning(disable:4996)

#define STKDUMP_DEBUG(fmt, ...) printf("%s:%d %s " fmt "\n", strrchr(__FILE__, '\\') + 1, __LINE__, __FUNCTION__, ##__VA_ARGS__)

//static bool getSymFromAddr(DWORD addr, char** name);
//static bool getAddr2Line(DWORD addr, char** out_line_info);

static STK_INFO _stk[32] = { 0 };
static int _stk_idx = 0;

bool get_cur_call_stack(STK_DATA* stk_data) {
	if (NULL == stk_data) {
		return false;
	}
	memset(_stk, 0, sizeof(_stk));
	_stk_idx = 0;

	int* cur_ebp = 0;
	__asm__ __volatile__("mov %%ebp, %%eax \n\t mov %%eax,%0":"=r"(cur_ebp));

	_stk[_stk_idx].depth = _stk_idx + 1;
	_stk[_stk_idx].bp = cur_ebp;
	_stk[_stk_idx].lr = (int*) (*(cur_ebp + 1));
	_stk[_stk_idx + 1].stk_top = cur_ebp + 1; //pre-stack frame's stack-top
	_stk_idx++;

	while (*cur_ebp) {
		if (_stk_idx >= sizeof(_stk) / sizeof(_stk[0])) {
			break;
		}
		cur_ebp = (int*) (*cur_ebp);
		_stk[_stk_idx].depth = _stk_idx + 1;
		_stk[_stk_idx].bp = cur_ebp;
		_stk[_stk_idx].lr = (int*) (*(cur_ebp + 1));// -1 ???
		_stk[_stk_idx + 1].stk_top = cur_ebp + 1; //pre-stack frame's stack-top
		_stk_idx++;
	}

	stk_data->stk_cnt = _stk_idx;
	int alloc_sz = _stk_idx * sizeof(STK_INFO);
	stk_data->stk_arr = (STK_INFO*) malloc(alloc_sz);
	memcpy(stk_data->stk_arr, _stk, alloc_sz);
	return true;
}

bool parse_1_stk(STK_DATA* stk_data) {
	if (NULL == stk_data) {
		return false;
	}

	for (int i = 0; i < stk_data->stk_cnt; ++i) {
		if (1){//!getSymFromAddr((DWORD) stk_data->stk_arr[i].lr, &stk_data->stk_arr[i].func_name)) {
			//STKDUMP_DEBUG("Failed to get Sym by addr, errNo:%u", ::GetLastError());
			stk_data->stk_arr[i].func_name = strdup("-");
		}

		if (1){//!getAddr2Line((DWORD) stk_data->stk_arr[i].lr, &stk_data->stk_arr[i].line_info)) {
			//STKDUMP_DEBUG("Failed to get line info by addr, errNo:%u", ::GetLastError());
			stk_data->stk_arr[i].line_info = strdup("-");
		}
	}
	return true;
}

void release_1_stk(STK_DATA* stk_data) {
	for (int i = 0; i < stk_data->stk_cnt; ++i) {
		free(stk_data->stk_arr[i].func_name);
		free(stk_data->stk_arr[i].line_info);
	}
	free(stk_data->stk_arr);
}

